/*
 * @Author: LVGRAPE
 * @LastEditors: LVGRAPE
 */
/*
 * @Author: LVGRAPE
 * @Date: 2024-01-10 17:37:49
 * @LastEditTime: 2025-10-11 01:53:55
 * @LastEditors: LVGRAPE
 * @Description:
 * @FilePath: \ble_aromatherapy_diffuser\AromatherapyDiffuser\hardware\W25QXX\getSbc.c
 * 要啥没啥，爱咋咋的
 */
#include <stdint.h>
#include "drv_serial.h"
#include "zino.h"
#include "w25qxx.h"
#include "usb_conf.h"

#define CMD_FLASH_HAND_SHAKE 0x1c
#define CMD_FLASH_ERASE_SECTOR 0x2c
#define CMD_FLASH_WRITE 0x3c
#define CMD_FLASH_WRITE_ADDR 0x4c
#define CMD_FLASH_WRITE_DATA 0x5c
#define CMD_FLASH_WRITE_INFO 0x6c
#define CMD_FLASH_READ_ADDR 0x7c
#define CMD_FLASH_READ_DATA 0x8c
#define CMD_FLASH_READ_INFO 0x9c

#define CMD_FLASH_ACK 0x1F
#define CMD_FLASH_NACK 0xF1
#define CMD_FLASH_EOK 0X00

uint8_t rbOut[256];
void msg_doCheck(struct msg_pack *msg)
{
    msg->data_check = 0;
    for (int i = 0; i < msg->data_size; i++)
    {
        msg->data_check ^= msg->data[i];
    }
}
int msg_Check(struct msg_pack *msg)
{
    uint8_t check = 0;
    for (int i = 0; i < msg->data_size; i++)
    {
        check ^= msg->data[i];
    }
    // co_printf("check:%02x expect:%02x\r\n", check, msg->data_check);
    return (check == msg->data_check);
}

// static int uart_putc(uint8_t c)
// {
//     return uart4_write(&c, 1);
// }
void com_putc(uint8_t ch)
{
    // vcp_send_data(&ch, 1);
    uart1_write(&ch, 1);
}
void com_put(uint8_t *data, int len)
{
    // vcp_send_data(data, len);
    uart1_write(data, len);
}
void get_data_task(int len, uint8_t *data)
{
    if (!len || len > MSG_PACK_SIZE)
        return;
    struct msg_pack *pack = (struct msg_pack *)data;

    if ((0xff == (pack->cmd[0] | pack->cmd[1])) && (0x00 == (pack->cmd[0] & pack->cmd[1])))
    {
        // co_printf("cmd check! %02X\r\n", pack->cmd[0]);
        switch (pack->cmd[0])
        {
        case CMD_FLASH_HAND_SHAKE:
            com_putc(CMD_FLASH_ACK);
            break;
        case CMD_FLASH_ERASE_SECTOR:
        {
            uint32_t addr = pack->addr[0] << 24 | pack->addr[1] << 16 | pack->addr[2] << 8 | pack->addr[3];
            // w25qxx_EraseSector(addr);
            // w25qxx_WaitBusy();
            flash_sector_erase(FLASH_SPIM_START_ADDR + addr);
            // rt_thread_mdelay(2);
            com_putc(CMD_FLASH_ACK);
            // co_printf("erase sector: %08X\r\n", addr);
        }
        break;
        case CMD_FLASH_WRITE_DATA:
            if (pack->data_size > MSG_DATA_SIZE_MAX)
            {
                com_putc(CMD_FLASH_NACK + 2);
            }
            else
            {
                // uart_putc( CMD_FLASH_ACK); REET
                if (msg_Check(pack))
                {
                    uint32_t addr = pack->addr[0] << 24 | pack->addr[1] << 16 | pack->addr[2] << 8 | pack->addr[3];
                    // w25qxx_WaitBusy();
                    // w25qxx_PageProgram(addr, pack->data, pack->data_size);
                    uint32_t *p_data = (uint32_t *)pack->data;
                    for (uint32_t wr_addr = addr; wr_addr < (addr + pack->data_size); wr_addr += 4)
                    {
                        flash_word_program(FLASH_SPIM_START_ADDR + wr_addr, *p_data);
                        p_data++;
                    }
                    for (uint32_t i = addr; i < pack->data_size; i++)
                    {
                        rbOut[i] = *(uint8_t *)(FLASH_SPIM_START_ADDR + i);
                        if (rbOut[i] != pack->data[i])
                        {
                            com_putc(CMD_FLASH_NACK + 3);
                            break;
                        }
                    }
                    com_putc(CMD_FLASH_ACK);
                }
                else
                {
                    com_putc(CMD_FLASH_NACK + 3);
                }
            }
            break;
        case CMD_FLASH_READ_DATA:
            if (pack->data_size > MSG_DATA_SIZE_MAX)
            {
                com_putc(CMD_FLASH_NACK);
            }
            else
            {
                uint32_t addr = pack->addr[0] << 24 | pack->addr[1] << 16 | pack->addr[2] << 8 | pack->addr[3];
                uint8_t txBuf[256];
                for (int i = 0; i < pack->data_size; i++)
                {
                    txBuf[i] = *(uint8_t *)(FLASH_SPIM_START_ADDR + addr + i);
                }
                // w25qxx_WaitBusy();
                // co_printf("read addr:%d size:%d\r\n",addr,pack->data_size );
                // w25qxx_FastRead(addr, txBuf, pack->data_size);
                for (int i = 0; i < pack->data_size; i++)
                {
                    com_putc(txBuf[i]);
                }
            }
            break;
        default:
            com_putc(CMD_FLASH_NACK);
            break;
        }
    }
    else
    {
        com_putc(CMD_FLASH_NACK + 1);
    }
    // co_delay_ms(1);
    // co_printf("cmd=%02x%02x,addr=%02x%02x%02x%02x,", pack->cmd[0], pack->cmd[1], pack->addr[0], pack->addr[1], pack->addr[2], pack->addr[3]);
    // co_printf("data_check:%d size:%d check:%d\r\n", pack->data_check, pack->data_size, msg_Check(pack));

    // for (int i = 0;i < pack->data_size;i++)
    // {
    //     co_printf("%02x ", pack->data[i]);
    // }
    // co_printf("\r\n");
}
